lexer grammar CommonLexer;

// Keywords

BREAK:              'break';
CASE:               'case';
CATCH:              'catch';
CHAR:               'char';
CLASS:              'class';
CONST:              'const';
CONTINUE:           'continue';
DEFAULT:            'default';
ELSE:               'else';
FINALLY:            'finally';
FOR:                'for';
IF:                 'if';
GOTO:               'goto';
IMPORT:             'import';
NEW:                'new';
PACKAGE:            'package';
RETURN:             'return';
STATIC:             'static';
SWITCH:             'switch';
THIS:               'this';
THROW:              'throw';
THROWS:             'throws';
TRY:                'try';
VOID:               'void';
WHILE:              'while';
FUNCTION:           'function';


// Literals
DECIMAL_LITERAL:    ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;
FLOAT_LITERAL:      (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]?
             |       Digits (ExponentPart [fFdD]? | [fFdD])
             ;

BOOL_LITERAL:       'true'
            |       'false'
            ;

STRING_LITERAL:     '"' (~["\\\r\n] | EscapeSequence)* '"'
              |     '\'' (~["\\\r\n] | EscapeSequence)* '\''
              ;

STRING_KEY: '"' (~["\\\r\n] | EscapeSequence)* '"'
          | '\'' (~["\\\r\n] | EscapeSequence)* '\''
          | Identifier
            ;

// Separators

LPAREN:             '(';
RPAREN:             ')';
LBRACE:             '{';
RBRACE:             '}';
LBRACK:             '[';
RBRACK:             ']';
SEMI:               ';';
COMMA:              ',';
DOT:                '.';

// Operators

ASSIGN:             '=';
GT:                 '>';
LT:                 '<';
NOT:               '!';
QUESTION:           '?';
COLON:              ':';
EQUAL:              '==';
LE:                 '<=';
GE:                 '>=';
NOTEQUAL:           '!=';
AND:                '&&';
OR:                 '||';
INC:                '++';
DEC:                '--';
ADD:                '+';
SUB:                '-';
MUL:                '*';
DIV:                '/';
MOD:                '%';

ADD_ASSIGN:         '+=';
SUB_ASSIGN:         '-=';
MUL_ASSIGN:         '*=';
DIV_ASSIGN:         '/=';
MOD_ASSIGN:         '%=';

// Java 8 tokens

NULL_LITERAL:       'null';

// Additional symbols not defined in the lexical specification
// Whitespace and comments

WS:                 [ \t\r\n\u000C]+ -> channel(HIDDEN);
COMMENT:            '/*' .*? '*/'    -> channel(HIDDEN);
LINE_COMMENT:       '//' ~[\r\n]*    -> channel(HIDDEN);

// Identifiers

Identifier:     Letter LetterOrDigit*;
//Identifier:   [a-zA-Z$_][a-zA-Z0-9$_]*;

// Fragment rules
fragment ExponentPart
    : [eE] [+-]? Digits
    ;

fragment EscapeSequence
    : '\\' [btnfr"'\\]
    | '\\' ([0-3]? [0-7])? [0-7]
    ;


fragment Digits
    : [0-9] ([0-9_]* [0-9])?
    ;

fragment LetterOrDigit
    : Letter
    | [0-9]
    ;

fragment Letter
    : [a-zA-Z$_] // these are the "java letters" below 0x7F
//    | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
//    | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
    ;
